<template>
  <div>
    <!-- 三级列表 -->
    <el-card shadow="always" :body-style="{ padding: '20px' }">
      <!-- 组件通讯：父组件传递值给子组件 把!isShowList传递给子组件 -->
      <CategorySelector :disabled="!isShowList"></CategorySelector>
    </el-card>

    <!-- 属性列表 -->
    <el-card shadow="always" :body-style="{ padding: '20px' }" style="margin-top: 20px;">
      <!-- 这个div就是我们的平台属性列表相关的东西 -->
      <div v-show="isShowList">
        <!-- 按钮 -->
        <!-- 添加属性按钮权限：没有获取到3级列表id(没有选择三级列表发送获取三级列表id)的时候不能点击 '添加属性' 按钮 -->
        <el-button :disabled="!category3Id" type="primary" size="default" icon="ele-Plus"  @click="showAddDiv">添加属性</el-button>
        <!-- 列表 -->
        <el-table :data="attrList" border stripe>
          <el-table-column label="序号" type="index" align="center" width="80"></el-table-column>
          <el-table-column label="属性名称" width="150" prop="attrName"></el-table-column>
          <el-table-column label="属性值名称列表">
            <!-- 作用域插槽 -->
            <template v-slot="{ row, $index }">
              <el-tag type="danger" size="default" v-for="(attrValue, index) in row.attrValueList" :key="attrValue.id">
                {{ attrValue.valueName }}
              </el-tag>
            </template>
          </el-table-column>
          <el-table-column label="操作" width="150">
            <!-- 作用域插槽 -->
            <template v-slot="{ row, $index }">
              <el-button type="warning" size="small" icon="ele-Edit" title="修改" @click="showUpdateDiv(row)"></el-button>
              <!-- 气泡框 -->
              <el-popconfirm :title="`你确定删除${row.attrName}吗？`" @confirm="deleteAttr(row)">
                <template #reference>
                  <el-button type="danger" size="small" icon="ele-Delete" title="删除"></el-button>
                </template>
              </el-popconfirm>
            </template>
          </el-table-column>
        </el-table>
      </div>

      <!-- 这个div对应的就是平台属性添加和修改的界面 -->
      <div v-show="!isShowList">
        <!-- input输入框 -->
        <el-form :inline="true">
          <el-form-item label="属性名">
            <el-input placeholder="请输入属性名" v-model="attrForm.attrName"></el-input>
          </el-form-item>
        </el-form>

        <!-- 两个按钮 -->
        <!-- 添加属性值按钮权限：在属性名输入框(attrForm.attrName)没有获取到值的时候不能点击 '添加属性值' 按钮 -->
        <el-button :disabled="!attrForm.attrName" type="primary" @click="addAttrValue">添加属性值</el-button>
        <el-button @click="isShowList=true">取消</el-button>
        <el-table :data="attrForm.attrValueList" border stripe style="margin-top: 20px;">
          <el-table-column label="序号" type="index" align="center" width="80"></el-table-column>
          <el-table-column label="属性值名称" prop="valueName">
            <!-- 作用域插槽 -->
            <template v-slot="{row,$index}">
              <!-- input输入框 -->
              <el-input ref="inputRef" size="small" v-if="row.isEdit" v-model="row.valueName" placeholder="请输入属性值名称" @blur="toLook(row,$index)" @keyup.enter="$event.target.blur()"></el-input>
              <!-- span框 -->
              <span v-else style="display: block; width: 100%;" @click="toEdit(row)"> {{ row.valueName }} </span>
            </template>
          </el-table-column>
          <el-table-column label="操作">
            <!-- 作用域插槽 -->
            <template v-slot="{row,$index}">
              <!-- 气泡框 -->
             <el-popconfirm :title="`确定要删除${row.valueName}吗？`" @confirm="attrForm.attrValueList.splice($index,1)">
              <template #reference>
                <!-- 按钮 -->
                <el-button type="danger" size="small" title="删除属性值" icon="ele-Delete"></el-button>
              </template>
            </el-popconfirm>
            </template>
          </el-table-column>
        </el-table>
        
        <!-- 两个按钮 -->
        <!-- 保存按钮权限：在attrForm.attrValueList.length为不空的时候(也就是点击了'添加属性值' 按钮 之后)，此时attrForm.attrValueList已经push了一个对象 才可以点击 '保存' 按钮 -->
        <el-button :disabled="!attrForm.attrValueList.length" type="primary" @click="save">保存</el-button>
        <el-button @click="isShowList=true">取消</el-button>
      </div>
    </el-card>

  </div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
export default defineComponent({
  name: 'Attr'
})
</script>
<script lang="ts" setup>
// icon单个使用需要引入，每个组件，上面在用的时候  :icon="组件"
// 为什么可以写ele-XXX是因为已经在SvgIcon当中把所有的组件已经在插件当中全局全部注册好了
// 名字在注册的时候，要求必须是ele开头
// import {Plus,Edit,Delete} from '@element-plus/icons-vue'

// 引入仓库
import { useCategoryStore } from '@/stores/category'
// 引入 storeToRefs
import { storeToRefs } from 'pinia';
// 引入监视器,ref
import { watch, ref } from 'vue'
// 引入api 引入数据类型
import AttrApi, { type AttrData, type AttrValueData } from '@/api/attr'
// 引入 element-plus 的 ElMessage
import { ElMessage } from 'element-plus';
// 引入 nextTick
import { nextTick } from 'vue';

/* 引入lodash */
// 1.完整引入
// import _ from 'lodash'
// 2.按需引入 一般默认选择这种
import { cloneDeep } from 'lodash';

// 发请求获取平台属性列表是在选中3级分类的时候才发的
// 此时我们就考虑拿到3级id，如果3级id发生变化我们就发请求
// 但是3级id发生变化  可能是这些情况
// 一开始没有，后面有了
// 一开始有，后面没了
// 一开始有，后来值变了
// 拿到仓库当中存储的3级分类id进行监视
// 获取到store对象
const categoryStore = useCategoryStore()
// 解构仓库当中的数据
const { category3Id, category1Id, category2Id } = storeToRefs(categoryStore)
// 请求发送成功获取到的数据存到本地
const attrList = ref<AttrData[]>([])
// 这个函数专门用来发请求获取属性列表
const getAttrList = async () => {
  try {
    // 传入参数发送请求
    const res = await AttrApi.getList(category3Id.value as number, category1Id.value as number, category2Id.value as number)
    // 把获取到的数据存起来
    attrList.value = res
  } catch (error) {
    ElMessage.error('获取平台属性列表失败')
  }
}
// 监视 category3Id
watch(category3Id, (newVal, oldVal) => {
  if (newVal !== '') {
    // 需要发请求的情况
    // 1. 一开始没有，后面有了
    // 2. 一开始有，后来值变了
    getAttrList()
  } else {
    // 不需要发请求的情况
    // 一开始有，后面没了
    // 不需要发送请求，但是需要把列表数据清空
    attrList.value = []
  }
}, {
  // 开启立即监听
  immediate: true
})




// 平台属性的添加
const isShowList = ref(true)
const  showAddDiv = () => {
  isShowList.value = false

  // 重置attrForm解决添加完成点取消再次添加的时候数据依然存在的bug
  attrForm.value = {
    attrName: '',
    attrValueList: [
      // {
      //   "attrId": 0,
      //   "id": 0,
      //   "valueName": "string"
      // }
    ],
    categoryId: category3Id.value,   //这里一定挂载完成，数据也都初始化结束了，此时拿数据最稳妥
    categoryLevel: 3, // 不需要收集，固定就是3级分类的id 
  }
}



// 收集数据
// {
//   "attrName": "string",
//   "attrValueList": [
//     {
      // "attrId": 0,
      // "id": 0,
      // "valueName": "string"
//     }
//   ],
//   "categoryId": 0,
//   "categoryLevel": 0,
//   "id": 0
// }
const attrForm = ref<AttrData>({
  attrName: '',
  attrValueList: [
    // {
    //   "attrId": 0,
    //   "id": 0,
    //   "valueName": "string"
    // }
  ],
  categoryId: '',   // 初始化数据的时候可能拿不到数据
  categoryLevel: 3, // 不需要收集，固定就是3级分类的id 
})

// ①定义 inputRef 用来获取input组件对象
const inputRef = ref()
// 点击添加属性值按钮
// 添加属性值的逻辑不光在添加属性的时候要用，在添加属性的时候添加属性值，属性的id是不存在的
// 在修改属性的时候也要用这个逻辑，在修改属性的时候添加属性值，属性的id是存在的

// 新添加的属性值，我们需要给添加一个模式数据 isEdit = true
const addAttrValue = () => {
  attrForm.value.attrValueList.push({
      "attrId": attrForm.value.id, // 添加属性的时候是undefined,修改属性的时候是有真实的id值的
      "valueName": '',
      isEdit:true // 用于条件渲染 新添加的一上来就是一个input
  })

  // 等页面更新完成以后
  nextTick(()=>{
    // ②调用input组件对象的focus()方法,来让input自动获取焦点
    inputRef.value.focus()
  })
}


// 点击修改属性的按钮逻辑
// 在这里面需要遍历属性的所有已存在属性值，添加 isEdit = false 用于条件渲染span
const showUpdateDiv = (row:AttrData) => {
  isShowList.value = false

  // 浅拷贝 只能改 对象.value 可以，页面数据不会变
  // 改 对象.value.value 是不行的，页面数据还是会变
  // attrForm.value = {...row}

  /* 所以这里需要深拷贝 */
  // 1. 完整引入之后的写法
  // attrForm.value = _.cloneDeep(row)
  // 2.按需引入之后的写法 一般选择默认引入
  attrForm.value = cloneDeep(row)

  // 给每个已存在的属性值添加 isEdit
  attrForm.value.attrValueList.forEach(item => item.isEdit = false) 
}


// 点击span切换input 就是让查看模式变为编辑模式
const toEdit = (row:AttrValueData) => {
  row.isEdit = true

  // 等页面更新完成以后
  nextTick(()=>{
    // ②调用imput组件对象的focus()方法,来让input自动获取焦点
    inputRef.value.focus()
  })
}

// input失去焦点切换span 就是让编辑模式变为查看模式
const toLook = (row:AttrValueData,index:number) => {
  // 1.判断输入的数据是不是空串，或者根本没输入
  if(!row.valueName || !row.valueName.trim()){
    ElMessage.error('输入的数据不能是空白')
    // 把这个空白删掉
    attrForm.value.attrValueList.splice(index,1)
    return 
  }

  // 2.判断输入的数据是不是和除了自己以外的已存在属性值名称重复
  let isRepeat = attrForm.value.attrValueList.some(item => {
    // 排除输入的自己（如果输入的和里面所有的地址都不一样，就继续执行下去）
    if(item !== row){
      // 判断有没有人和自己一样，如果有就返回turn 没有就返回false
      return item.valueName === row.valueName
    }
  })
  // 如果有重复的
  if(isRepeat){
    ElMessage.error('输入的数据不能重复')
    // 清空输入的数据
    row.valueName = ''
    return
  }
  // 前面1、2、两关都过了才会变成span
  row.isEdit = false
}



// 点击保存，保存逻辑
const save = async () => {
  // 1.获取请求参数
  let attr = attrForm.value
  // 2.整理参数：
  // 1）属性值名称如果为空串，从属性值列表当中去除
  // 2）属性值当中去除isEdit属性
  attr.attrValueList = attr.attrValueList.filter(item => {
    if(item.valueName !== ''){
      delete item.isEdit
      return true
    }
  })
  // 3）属性值列表如果没有属性值，不发请求
  if(attr.attrValueList.length === 0){
    return
  }
  // 3.发请求
  try {
    // 4.成功干什么
    await AttrApi.addOrUpdate(attr)
    // 成功信息提示
    ElMessage.success('保存平台属性成功')
    // 关闭平台属性添加和修改的界面
    isShowList.value = true
    // 刷新界面
    getAttrList()
  } catch (error) {
    // 5.失败干什么
    // 失败信息提示
    ElMessage.error('保存平台属性失败')
    // 关闭平台属性添加和修改的界面
    isShowList.value = true
  }
}


// 点击列表页删除，删除属性
const deleteAttr = async (row:AttrData) => {
  try {
    // 传参发送api请求
    await AttrApi.delete(row.id as number)
    // 删除成功信息提示
    ElMessage.success('删除平台属性成功')
    // 刷新页面
    getAttrList()
  } catch (error) {
    // 删除失败信息提示
    ElMessage.error('删除平台属性失败')
  }
}
</script>

<style lang="less" scoped></style>
